#include <iostream>

template< typename TT, typename VT >
const VT Object<TT,VT>::operator[]( unsigned int pos ) {
  return vertexBuffer->verts[pos];
}

template< typename TT, typename VT >
ObjectManager<TT,VT>::
ObjectManager( CreateFunc func ) : currentLoc(0), CreateBufferFromFile(func) { 
  objectRefs.push_back(RefObj()); 
}

template< typename TT, typename VT >
ObjectManager<TT,VT>::
~ObjectManager() {
  unsigned int size = (unsigned int)objectRefs.size();
  for( unsigned int i = 0; i < size; ++i ) {
    if( objectRefs[i].buffer.verts ) {
      delete( objectRefs[i].buffer.verts );
    }
  }
}

template< typename TT, typename VT >
Object<TT,VT> ObjectManager<TT,VT>::
CreateObject( std::string objectName ) { // Complete Yeah
  Obj temp; // Object looking at nothing

  StrIdIter iter = nameToId.find( objectName );
  if( iter != nameToId.end() ) {
    RefObj& tempRef = objectRefs[iter->second];
    ++tempRef.refCount;

    temp.vertexIndex  = iter->second;
    temp.vertexBuffer = &(tempRef.buffer);
  }

  return temp;
}

template< typename TT, typename VT >
void ObjectManager<TT,VT>::
DeleteObject( Obj& object ) {
  if( object.vertexIndex ) {
    RefObj& tempRef = objectRefs[object.vertexIndex];

    if( tempRef.refCount )
      --tempRef.refCount;

    if( !tempRef.refCount && !tempRef.isStatic ) {
      if( tempRef.buffer.verts ) {
        delete( tempRef.buffer.verts );
        tempRef.buffer.verts = NULL;
      }

      StrIdIter iter = nameToId.find( tempRef.objectName );
      if( iter != nameToId.end() ) {
        nameToId.erase( iter );
      }
      ReleaseLoc( object.vertexIndex );
    }
  }
  
  object.vertexIndex = 0;
  object.vertexBuffer = NULL;
}

template< typename TT, typename VT >
void ObjectManager<TT,VT>::
ChangeObject( Obj& object, std::string objectName ) {
  DeleteObject( object );
  object = CreateObject( objectName );
}

template< typename TT, typename VT >
void ObjectManager<TT,VT>::
GenerateObject( std::string objectName, std::string dataFile, bool isStatic ) {
  IdValue objLoc = 0;
  StrIdIter iter = nameToId.find( objectName );
  if( iter == nameToId.end() ) {
    StrIdPair temp( objectName, GetNewLoc() );
    nameToId.insert( temp ); //$$$ Add check

    if( temp.second == currentLoc ) { // Location is at end of vector
      objectRefs.push_back( RefObj() ); //$$$ Add check
    }

    objectRefs[temp.second].objectName = objectName;
    objectRefs[temp.second].isStatic = isStatic;
    objLoc = temp.second;
  }
  else {
    objLoc = iter->second;
  }

  RefObj& genObj = objectRefs[objLoc];
  if( genObj.buffer.verts ) {
    delete( genObj.buffer.verts );
  }
  
  const VT* oldBuffer = genObj.buffer.verts;
  genObj.buffer.verts = CreateBufferFromFile( dataFile.c_str(), genObj.buffer.vertCount );
  
  if( oldBuffer ) {
    delete (oldBuffer);
  }
}


template< typename TT, typename VT >
typename ObjectManager<TT,VT>::IdValue ObjectManager<TT,VT>::
GetNewLoc() {
  if( deletedLocs.size() ) {
    IdValue temp = deletedLocs[deletedLocs.size()-1];
    deletedLocs.pop_back();
    return temp;
  }

  ++currentLoc;
  return currentLoc;
}

template< typename TT, typename VT >
void ObjectManager<TT,VT>::
ReleaseLoc( IdValue val ) {
  deletedLocs.push_back( val );
}
